package com.cxm.helper.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cxm.helper.enums.UserRoleEnum;
import com.cxm.helper.enums.UserStatusEnum;
import com.cxm.helper.exception.BusinessException;
import com.cxm.helper.mapper.ArticleMapper;
import com.cxm.helper.pojo.Config;
import com.cxm.helper.pojo.User;
import com.cxm.helper.pojo.dto.UserListDTO;
import com.cxm.helper.pojo.dto.UserRegDTO;
import com.cxm.helper.pojo.dto.UserUpdateDTO;
import com.cxm.helper.pojo.vo.ArticleNumGroupVO;
import com.cxm.helper.pojo.vo.CategoryVO;
import com.cxm.helper.pojo.vo.UserVO;
import com.cxm.helper.service.ArticleService;
import com.cxm.helper.service.ConfigService;
import com.cxm.helper.service.UserLikeService;
import com.cxm.helper.service.UserService;
import com.cxm.helper.mapper.UserMapper;
import com.cxm.helper.util.BeanUtil;
import com.cxm.helper.util.MD5Util;
import com.cxm.helper.util.RedisUtil;
import com.cxm.helper.util.constant.RedisKeyConstant;
import com.cxm.helper.util.response.PageResponse;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @author chenximeng
* @description 针对表【user】的数据库操作Service实现
* @createDate 2022-11-18 09:13:45
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService{

    @Autowired
    UserMapper userMapper;
    @Autowired
    MD5Util md5Util;
    @Autowired
    ConfigService configService;
    @Autowired
    ArticleMapper articleMapper;
    @Autowired
    UserLikeService userLikeService;
    @Autowired
    ArticleService articleService;
    @Autowired
    RedisUtil redisUtil;

    @Override
    public UserVO login(String phone, String password, boolean isAdmin) {
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("phone", phone));
        if (user == null) {
            throw new BusinessException("账号不存在");
        }
        if (!user.getPassword().equals(md5Util.doMd5(password))) {
            throw new BusinessException("密码错误");
        }

        if (user.getStatus() == UserStatusEnum.DISABLE.getCode()) {
            throw new BusinessException("账号被禁用");
        }

        if (isAdmin && !user.getAdmin().equals(UserRoleEnum.ADMIN.getCode())) {
            throw new BusinessException("非管理员账户");
        }
        return formatUser(user);
    }

    public UserVO formatUser(User user) {
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        Config config = configService.getByConfigName(user.getMajorCode());
        if (config != null) {
            userVO.setMajorName(config.getConfigValue());
        }
        List<ArticleNumGroupVO> list = articleMapper.listArticleNumByUserIds(CollUtil.newArrayList(user.getId()));
        if (CollUtil.isEmpty(list)) {
            userVO.setArticleNum(0L);
            return userVO;
        }
        ArticleNumGroupVO num = list.get(0);

        userVO.setArticleNum(0L);
        if (num != null) {
            userVO.setArticleNum(num.getArticleNum());
        }

        return userVO;
    }

    /**
     * @param dto
     * @return
     */
    @Override
    public UserVO reg(UserRegDTO dto) {
        String redisKey = dto.getPhone() + RedisKeyConstant.PHONE_SMS_REG_SUFFIX;
        String redisCode = redisUtil.get(redisKey);
        if (!dto.getSmsCode().equals(redisCode)) {
            throw new BusinessException("验证码错误");
        }

        dto.setPassword(md5Util.doMd5(dto.getPassword()));
        User user = new User();
        BeanUtils.copyProperties(dto, user);
        userMapper.insert(user);
        return formatUser(user);
    }

    @Override
    public void update(UserUpdateDTO dto) {
        User user = new User();
        BeanUtils.copyProperties(dto, user);
        user.setId(StpUtil.getLoginIdAsLong());
        User old = getById(user.getId());
        if (StrUtil.isNotBlank(dto.getOldPassword()) && !old.getPassword().equals(md5Util.doMd5(dto.getOldPassword()))) {
            throw new BusinessException("旧密码不正确");
        }
        if (StrUtil.isNotBlank(dto.getPassword())) {
            user.setPassword(md5Util.doMd5(dto.getPassword()));
        }
        user.setId(StpUtil.getLoginIdAsLong());
        userMapper.updateById(user);
    }

    @Override
    public boolean verifyNickname(String nickname) {
        return CollUtil.isEmpty(userMapper.selectList(new QueryWrapper<User>().eq("nickname", nickname)));
    }

    @Override
    public PageResponse list(UserListDTO userListDTO) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        if (StrUtil.isNotBlank(userListDTO.getKeyword())) {
            wrapper.like("nickname", userListDTO.getKeyword());
        }
        if (CollUtil.isNotEmpty(userListDTO.getRoleList())) {
            wrapper.in("admin", userListDTO.getRoleList());
        }
        if (CollUtil.isNotEmpty(userListDTO.getStatusList())) {
            wrapper.in("status", userListDTO.getStatusList());
        }
        Page<User> page = new Page<>(-1, -1);
        if (userListDTO.getCurrent() != null) {
            page = new Page<>(userListDTO.getCurrent(), userListDTO.getSize());
        }
        IPage<User> result = userMapper.selectPage(page, wrapper);

        List<User> users = result.getRecords();
        if (CollUtil.isEmpty(users)){
            return new PageResponse<CategoryVO>(result.getCurrent(), result.getTotal(), result.getSize(), CollUtil.newArrayList());
        }
        List<UserVO> list = BeanUtil.copyList(users, UserVO.class);
        List<Long> userIds = users.stream().map(User::getId).collect(Collectors.toList());
        List<ArticleNumGroupVO> numsList = articleMapper.listArticleNumByUserIds(userIds);
        Map<Long, Long> articleNumMap = numsList.stream().collect(Collectors.toMap(ArticleNumGroupVO::getUserId, ArticleNumGroupVO::getArticleNum));
        for (UserVO userVO : list) {
            userVO.setArticleNum(articleNumMap.get(userVO.getId()) == null ? 0 : articleNumMap.get(userVO.getId()));
        }
        return new PageResponse<>(page, list);
    }

    @Override
    public Integer updateRole(Long id) {
        User user = getById(id);
        user.setAdmin(UserRoleEnum.reversCode(user.getAdmin()));
        updateById(user);
        return user.getAdmin();
    }

    @Override
    public Integer updateStatus(Long id) {
        User user = getById(id);
        user.setStatus(UserRoleEnum.reversCode(user.getStatus()));
        updateById(user);
        return user.getStatus();
    }

    @Override
    public boolean verifyPhone(String phone) {
        return CollUtil.isEmpty(userMapper.selectList(new QueryWrapper<User>().eq("phone", phone)));
    }

}




